home *** CD-ROM | disk | FTP | other *** search
- Date: Tue Jun 16 1992 11:05:08
- From: Ted Jensen
- To: Michael Halcrow
- Subj: Pointers & things
- Attr:
- international C echo
- -------------------------------
- Michael-
-
- In reading your messages to Mike Dalsanto, Robert Place, and
- All I see you need some help on pointers, arrays, and strings.
- Perhaps the following will help:
-
- A string is a one dimensional array of characters. A one
- dimensional array of a given type is contiguous in memory with
- each element following in memory the one preceding it.
-
- A pointer is a variable much like any other variable. For
- example, let's consider a more easily understood variable, the
- integer:
-
- int k;
-
- defines an integer and reserves x bytes of space in memory
- for its storage. The number of bytes reserved depends on the
- system and/or compiler. For DOS systems an integer requires 2
- bytes of storage. Defining an integer, as above, does not give
- it a value. If it is defined as a global variable, it will be
- intialized it to zero. If it is defined as an auto variable
- (i.e. within a function) its value is indeterminate (i.e. a
- random value). Before use, the safest thing to do with any
- variable is to intialize it to some value (though in this case
- most (all?) compilers will intialize it to zero if it is global.
-
- Now, let's look at a pointer to the type integer which can be
- defined as:
-
- int *int_ptr;
-
- defines a pointer and reserves x bytes of space in memory for
- its storage. The number of bytes reserved depends on the system
- and/or compiler. But, fundamentally, since a pointer is designed
- to hold an address in memory, it must reserve the number of bytes
- necessary to contain such an address. Defining a pointer, as
- above, does not give it a value. If it is defined as a global
- variable it will be initialzed to a NULL, i.e. the address it
- will contain (which is the same as saying "the address to which
- it points to") will be set to a value of NULL which is #defined
- in <stdio.h>. In DOS systems, NULL is defined as the address of
- the first byte of the data segment. In Borland products, the
- first few bytes of the data segment contain a copyright notice.
- Before use, a pointer _must_ be "pointed at something", i.e.
- assigned a value equal to the address of some data item. More on
- this later.
-
- The key to understanding pointers is to remember that they
- are variables which contain addresses and that when we say a
- pointer "points to something", we mean that it contains the
- address of another variable or some other point in memory (such
- as the video screen buffer).
-
- Suppose now, that I want to "point" my integer pointer,
- int_ptr, at my integer k. We do this as follows:
-
- int_ptr = &k;
-
- Why use the '&'? Well, let's say k = 7;, were we to write
- "int_ptr = k;" we would be "pointing our pointer" at memory
- location 7. But what we want is to "point our pointer" to the
- memory location where the value of k is stored, which is an
- entirely different thing. By preceding the 'k' with the '&' we
- get the that address where the value of k is stored and point the
- pointer where we intend.
-
- Now, let's move on to arrays, and eventually arrays of
- characters which, in some languages, are called strings. But
- first, let's discuss an array of integers as in:
-
- int int_array[5];
-
- defines an array capable of holding 5 integers. We could then
- intialize these with statement such as: int_array[0] = 4; ,
- int_array[1] = 7 , etc. Or, we could initialize the array at the
- same time as we define it with:
-
- int int_array[5] = { 4, 7, 2, -2, 6 };
-
- The 5 memory locations for these integers will be contiguous
- in memory, i.e. if the 4 is stored at memory location 1000, it is
- gauranteed that the 7 will be stored at memory location 1002
- (recall an integer takes 2 bytes of storage) and the 2 will be
- stored at 1004, etc.
-
- Recall that we stated that &k returned the address where the
- value of the integer k was stored. Similarly
-
- &int_array[0] will return the memory location of the
- first integer in the array. Thus, if we want to point our
- pointer at the array (i.e. the first element of the array) we can
- write:
-
- int_ptr = &int_array[0];
-
- However, with arrays, there is a second option. The name of our
- array will also return the memory location of the first element.
- This means that we can write:
-
- int_ptr = int_array;
-
- and get exactly the same result.
-
- With that as background, let's now turn to "strings", (called
- character arrays in C). Everything we said about integer arrays
- can also be said about character arrays. Thus:
-
- char c_array[20]; /* reserves space for 20 characters */
- char *c_ptr; /* an (unitialized) pointer to a
- character */
-
- c_ptr = &c_array[0]; /* points the pointer at the first
- char of the array ("string") */
-
- c_ptr = c_array; /* does the same */
-
- Note that &c_array is meaningless.
-
- char c_array[] = { 'M', 'i', 'c', 'h', 'a', 'e', 'l', '\0' };
-
- This last line intializes c_array to hold "Michael".
- However, with character arrays, the above line can be written
- using a sort of shorthand as:
-
- char c_array[] = "Michael";
-
- Note that in the later case, the space reserved will be 8
- bytes and the 8th byte will automatically be set to '\0' so that
- this syntax is, in fact, shorthand for the longer method
- preceding it.
-
- Now, let's to back to pointers and discuss them in context
- with functions. Consider the following function:
-
- void do_something(int k, int *p);
-
- If you have studied functions you know that parameters are
- passed by _value_. That is, if k = 7, what gets passed as a
- parameter is the value 7 (as distinguished from the address of
- k). Similarly, what gets passed for the second parameter is the
- value of p. But, the value of p is an address. Thus, the
- following three calls to do_something are equivalent:
-
- int k = 7;
- int int_arr[5] = { 1, 2, 3, 4, 5 };
- int *pk;
- int *pa;
- pk = &k;
- pa = int_arr;
-
- do_something( 3, pk );
- do_something( 3, &k );
-
- Similarly, these three calls to our function
-
- do_something( 3, pa);
- do_something( 3, &int_arr[0]);
- do_something( 3, int_arr);
-
- are identical, i.e. the _value_ of the second parameter is the
- same in all three cases. This frees the programmer to choose
- that approach which he/she is more comfortable with.
-
- Now, let's talk about "strings" some more. There is one more
- kind of "string" that we have yet to discuss. It is called the
- "literal string". A literal string is any string in your code
- that appears in quotes. Thus, in all the following cases the
- string "l_string" is a literal string.
-
- char s_arr[] = "l_string";
- fopen("my_file", "wb");
- strcpy(s_arr, "l_string");
- printf("This is a test");
-
- During the compilation process, whenever and where ever the
- compiler sees a literal string it a) reserves space in the data
- segment to hold the string, b) puts the string within the quotes
- in that space and terminates it with the '\0' character, and c)
- replaces the literal string in the statement with a pointer
- "pointing to" the memory location where it is stored.
-
- Thus, for example, if the compiler sees:
-
- strcpy(s_arr, "l_string");
-
- it moves the characters "l_string\0" to a memory location in the
- data segment, lets say it is at DS:0205. It then "modifies" the
- statement to read:
-
- strcpy(s_arr, DS:0205); And if s_arr is located at DS:0097,
-
- it becomes:
-
- strcpy(DS:0097, DS:0097);
-
- Thus, if you look at the prototype for strcpy(), located in
- <string.h>, you will see something like:
-
- char *strcpy(char *p1, char *p2);
-
- which indicates that this function should be passed "pointers".
- But, now we know that it _really_ means that the function should
- be passed the _values_ of these pointers, which are _addresses_.
- And because we also recognize that the compiler replaces literal
- strings with addresses, a statment such as:
-
- strcpy(s_arr, "Michael");
-
- begins to make some sense (at least I hope it does!).
-
- Michael, I have just scratched the surface here. Other things
- that need "going into" include how and why the compiler _always_
- converts array notation to pointer notation as in converting:
-
- a[n] to *(a + n);
-
- Why are arrays always based at zero? i.e. why is the first
- element of an array always referred to as array[0] and not
- array[1]? Why does something like:
-
- char *p = "This is a test";
-
- initialize a string much the same as;
-
- char arr[] = "This is a test"; but with different results.
-
- There are dozens of other issues that you will learn as you gain
- experience. In the long run, you will find that C is much more
- powerful than BASIC. But, having the power makes it more
- difficult to use. One can add, subtract, multiply or divide with
- pencil and paper, and this is the way we all learn in the
- beginning. A little later we learn there is a machine that we
- can use to do this called a calculator, and this does things
- faster. Further more, calculators come in various degrees of
- complexity, including some that can be programmed. When using
- the more complex calculators we must have a little more knowledge
- and take a little more care to avoid errors.
-
- As we move up this chain of experience we eventually come to
- computers where, once again, we can still add, subtract,
- multiply, and divide, but to do so (in a program) requires still
- more knowledge and care. With each increase in power comes the
- need for more knowledge and the attainment of more flexibility
- (ever try and do wordprocessing on a four function calculator?).
-
- If you want to use sharper knives to make your task easier, you
- just have to be more careful not to cut yourself since the cut
- will go a lot deeper!
-
- At the point you are in your development of skills with C, I
- _strongly_ recommend you purchase:
-
- "The C Programming Language" (2nd edition)
- Kernighan and Ritchie
- Prentice Hall
-
- This is the 2nd edition of the book that started it all. The
- authors were the ones who developed the C language and the book,
- often referred to as K&R or K&R2, is the _true_ bible for C
- users. If you start at page 1, take it slow, and read it
- carefully, it will really pay off and it won't be any time at all
- before you are answering the questions here that you are now
- asking!
-
- Hope this helps! ... and good luck!
-